﻿using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Library.Helper;

namespace Library.Middlewares
{
    public class ExceptionHandleMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IHostEnvironment _env;
        private readonly ILogger<ExceptionHandleMiddleware> _logger;
        private static readonly string key = "enterTime";
        public ExceptionHandleMiddleware(RequestDelegate next, IHostEnvironment env, ILogger<ExceptionHandleMiddleware> logger)
        {
            _next = next;
            _env = env;
            _logger = logger;
        }

        public async Task InvokeAsync(HttpContext httpContext)
        {
            try
            {
                await _next(httpContext);
            }
            catch (Exception ex)
            {
                await HandleExceptionAsync(httpContext, ex);
            }
        }

        private Task HandleExceptionAsync(HttpContext context, Exception exception)
        {
            context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

            var error = _env.IsDevelopment() ? exception.ToString() : exception.Message;
            _logger.LogError(error);
            context.Response.ContentType = "application/json";
            _= OnResultExecutionAsync(context, _next
             , error);
            return context.Response.WriteAsync(JsonConvert.SerializeObject(new MessageModel<string> {msg=error}, new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            }));
        }
        /// <summary>
        /// 在请求执行完后 记录请求的数据以及返回数据
        /// </summary>
        /// <param name="actionExecutedContext"></param>
        /// <param name="next">下一个结果</param>
        /// <param name="error">错误信息</param>
        /// <returns></returns>
        public async Task OnResultExecutionAsync(HttpContext actionExecutedContext, RequestDelegate next, string error)
        {
            try
            {
                if (actionExecutedContext.Response.StatusCode != 200)
                {
                    //actionExecutedContext.HttpContext.Response.OnCompleted(() =>
                    //{
                    actionExecutedContext.Request.Body.Position = 0;
                    //var syncIOFeature = actionExecutedContext.HttpContext.Features.Get<IHttpBodyControlFeature>();
                    //if (syncIOFeature != null) { syncIOFeature.AllowSynchronousIO = true; }
                    object beginTime = null;
                    if (actionExecutedContext.Items.TryGetValue(key, out beginTime))
                    {
                        DateTime time = DateTime.FromBinary(Convert.ToInt64(beginTime));
                        //actionExecutedContext.HttpContext.Request.EnableBuffering(0, 3000);//可以读取流中的数据
                        HttpRequest request = actionExecutedContext.Request;
                        //string token = request.Headers["HospitalId"];
                        //string userId = request.Headers["UserId"];
                        //string depId = request.Headers["departmentId"];
                        var resultObj = actionExecutedContext.Response; //"Value":{ "ResultStatus":"200","Msg":"好的","ResultData":[],"RecordSn":null}
                        //string resultjson = Newtonsoft.Json.JsonConvert.SerializeObject(error);
                        //string regstring = "(?<=\"Value\":).+(?=,\"Format)";
                        //var regex = new System.Text.RegularExpressions.Regex(regstring);
                        //var data = regex.Match(resultjson)?.Value;
                        //HttpLogEntity apiActionLog = new HttpLogEntity
                        //{
                        //    //获取action名称 
                        //    ACTIONNAME = actionExecutedContext.Request.RouteValues["Action"]?.ToString(),
                        //    //获取Controller 名称
                        //    CONTROLLERNAME = actionExecutedContext.Request.RouteValues["Controller"]?.ToString(),
                        //    //获取action开始执行的时间
                        //    ENTERTIME = time,
                        //    //获取执行action的耗时
                        //    COSTTIME = Convert.ToDecimal((DateTime.Now - time).TotalMilliseconds),
                        //    NAVIGATOR = request.Protocol,
                        //    //TOKEN = token,
                        //    //USERID = userId,
                        //    //获取用户token
                        //    //userId = "token",
                        //    //获取访问的ip
                        //    IP = actionExecutedContext.Connection.RemoteIpAddress.ToString(),
                        //    BROWSER = request.Headers["User-Agent"].ToString().Substring(0, 49),
                        //    //USERHOSTNAME = request.UserHostName,
                        //    //URLREFERRER = request.UrlReferrer != null ? request.UrlReferrer.AbsoluteUri : "",
                        //    //BROWSER = request.Browser.Browser + " - " + request.Browser.Version + " - " + request.Browser.Type,
                        //    //获取request提交的参数
                        //    PARAMATERS = GetRequestValues(actionExecutedContext).Result,
                        //    //获取response响应的结果
                        //    EXCUTERESULT = error,
                        //    STATE = 1,
                        //    //COMMENTS = string.IsNullOrEmpty(msg) ? depId : msg,
                        //    REQUESTURI = request.Host.Value + request.Path.ToUriComponent() + request.QueryString.Value
                        //};
                        //apiActionLog.STATE = Convert.ToInt16(actionExecutedContext.Response.StatusCode);
                        //if (apiActionLog.EXCUTERESULT.Length > 2999)
                        //    apiActionLog.EXCUTERESULT = "";
                        //if (apiActionLog.PARAMATERS.Length > 2999)
                        //    apiActionLog.PARAMATERS = "";
                        //var tra = _test.Database.BeginTransaction();
                        //try
                        //{
                        //    _ = _httpLogRepository.AddAsync(apiActionLog);
                        //}
                        //catch
                        //{

                        //}
                    }

                }
            }
            catch (Exception)
            {

            }
            await Task.CompletedTask;
        }
        /// <summary>
        /// 读取request 的提交内容
        /// </summary>
        /// <param name="actionExecutedContext"></param>
        /// <returns></returns>
        public async Task<string> GetRequestValues(HttpContext actionExecutedContext)
        {
            try
            {
                //Stream stream = actionExecutedContext.HttpContext.Request.Body;
                //Encoding encoding = Encoding.UTF8;
                /*
                    这个StreamReader不能关闭，也不能dispose
                    因为关掉后，后面的管道  或拦截器就没办法读取了
                */
                var reader = new StreamReader(actionExecutedContext.Request.Body);
                string result = await reader.ReadToEndAsync();
                if (string.IsNullOrEmpty(result))
                {
                    result = reader.ReadToEnd();
                }
                /*
                这里也要注意：   stream.Position = 0;
                当你读取完之后必须把stream的位置设为开始
                因为request和response读取完以后Position到最后一个位置，交给下一个方法处理的时候就会读不到内容了。
                */
                actionExecutedContext.Request.Body.Position = 0;
                return result;
            }
            catch (Exception)
            {
                return "";
            }
        }
    }
}
